package com.kang.controller;

import cn.hutool.http.server.HttpServerRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.kang.config.ApplicationContextRegister;
import com.kang.entity.ChatRecord;
import com.kang.entity.ChatRecordNum;
import com.kang.service.ChatRecordNumService;
import com.kang.service.ChatRecordService;
import com.kang.util.SocketMsg;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;

@ServerEndpoint(value = "/user/websocket/{id}")
@Component
public class WebSocketService {

    private Integer id;
    private Session session;

    //用来存放每个客户端对应的MyWebSocket对象。
    private static final CopyOnWriteArraySet<WebSocketService> webSocketSet = new CopyOnWriteArraySet<WebSocketService>();
    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    //用来记录sessionId和该session进行绑定
    private static final Map<String, Session> map = new HashMap<>();

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void  onOpen(Session session, @PathParam("id") Integer id) {
        Map<String,Object> message=new HashMap<>();
        this.session = session;
        this.id = id;
        map.put(String.valueOf(id), session);
        webSocketSet.add(this);//加入set中
        System.out.println("有新连接加入:" + id + ",当前在线人数为" + webSocketSet.size());
        //this.session.getAsyncRemote().sendText("恭喜" + nickname + "成功连接上WebSocket(其频道号：" + session.getId() + ")-->当前在线人数为：" + webSocketSet.size());
        message.put("type",0); //消息类型，0-连接成功，1-用户消息
        message.put("people",webSocketSet.size()); //在线人数
        message.put("name",id); //昵称
        message.put("aisle","频道号："+id+"上线了！"); //频道号
        broadcast(new Gson().toJson(message));
        //this.session.getAsyncRemote().sendText(JsonUtils.objectToJson(message));
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        map.remove(String.valueOf(this.id));
        webSocketSet.remove(this); //从set中删除
        Map<String,Object> m=new HashMap<>();
        m.put("type",0);
        m.put("people",webSocketSet.size());
        m.put("aisle",this.id+"频道下线了！");
        broadcast(new Gson().toJson(m));
        System.out.println("有一连接关闭！当前在线人数为" + webSocketSet.size());
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session, @PathParam("id") Integer id) {
        System.out.println("来自客户端的消息-->" + id + ": " + message);

        //从客户端传过来的数据是json数据，所以这里使用jackson进行转换为SocketMsg对象，
        // 然后通过socketMsg的type进行判断是单聊还是群聊，进行相应的处理:
        ObjectMapper objectMapper = new ObjectMapper();
        SocketMsg socketMsg;

        try {
            socketMsg = objectMapper.readValue(message, SocketMsg.class);
            ChatRecordService chatRecordService = ApplicationContextRegister.getApplicationContext().getBean(ChatRecordService.class);
            ChatRecordNumService chatRecordNumService = ApplicationContextRegister.getApplicationContext().getBean(ChatRecordNumService.class);
            // System.out.println(message);
            if (socketMsg.getType() == 1) {
                //单聊.需要找到发送者和接受者.
                socketMsg.setFromUser(String.valueOf(this.id));//发送者.
                Session fromSession = map.get(socketMsg.getFromUser());
                Session toSession = map.get(socketMsg.getToUser());
                //发送给接受者.
                if (toSession != null) {
                    //发送给发送者.
                    Map<String,Object> m=new HashMap<>();
                    m.put("type",1);
                    m.put("id",id);    //发送着的id
                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
                    m.put("time", df.format(new Date()));
                    m.put("msg",socketMsg.getMsg());
                    m.put("receiveUserId",Integer.valueOf(socketMsg.getToUser()));
                    ChatRecord chatRecord = new ChatRecord(this.id,Integer.valueOf(socketMsg.getToUser()),1,socketMsg.getMsg(),new Date(),new Date());
                    chatRecordService.insertChatRecord(chatRecord);
                    fromSession.getAsyncRemote().sendText(new Gson().toJson(m));
                    m.put("id",Integer.valueOf(socketMsg.getFromUser()));
                    toSession.getAsyncRemote().sendText(new Gson().toJson(m));
                } else {
                    ChatRecord chatRecord = new ChatRecord(this.id,Integer.valueOf(socketMsg.getToUser()),2,socketMsg.getMsg(),new Date(),new Date());
                    chatRecordService.insertChatRecord(chatRecord);
                    //发送给发送者. 用来统计当前未读信息数
                    ChatRecordNum chatRecordNum = new ChatRecordNum(this.id,Integer.valueOf(socketMsg.getToUser()),1,new Date(),new Date());
                    chatRecordNumService.insertChatRecordNum(chatRecordNum);
                    Map<String,Object> m=new HashMap<>();
                    m.put("type",1);
                    m.put("id",id);    //发送着的id
                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
                    m.put("time", df.format(new Date()));
                    m.put("msg",socketMsg.getMsg());
                    m.put("receiveUserId",Integer.valueOf(socketMsg.getToUser()));
                    fromSession.getAsyncRemote().sendText(new Gson().toJson(m));
                    m.put("id",Integer.valueOf(socketMsg.getToUser()));
                }
            } else {
                //群发消息
                Map<String,Object> m=new HashMap<String, Object>();
                m.put("type",1);
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
                m.put("time", df.format(new Date()));
                m.put("id",id);
                m.put("msg",socketMsg.getMsg());
                broadcast(new Gson().toJson(m));
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("发生错误");
        error.printStackTrace();
    }

    /**
     * 群发自定义消息
     */
    public void broadcast(String message) {
        for (WebSocketService item : webSocketSet) {
            item.session.getAsyncRemote().sendText(message);//异步发送消息.
        }
    }
 
}